package com.actionsoft.tokendemo;

import com.actionsoft.bpms.server.bind.annotation.Controller;
import com.actionsoft.bpms.server.bind.annotation.HandlerType;
import com.alibaba.nacos.common.http.param.MediaType;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import javax.ws.rs.*;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * TOKEN获取RESTful API - 完全按照图片文档规范实现
 *
 * JSON返回格式严格按照图片要求：
 * {
 *   "rbCode": "业务返回码",
 *   "code": 200,
 *   "rbMsg": "返回信息",
 *   "saToken": "Token令牌"
 * }
 */
@Controller(type = HandlerType.RESTFUL, apiName = "tokenapi", desc = "TOKEN获取接口")
@Path("/api/tokenApi/token")
public class TokenDemoController {

    // 服务ID
    private static final String SERVICE_ID = "158000000123";
    // 商务密匙
    private static final String TRAD = "457f792ba3c44d0f9426b30d11ff3647";
    // TOKEN请求地址
    private static final String TOKEN_URL = "https://s.bitzh.edu.cn/mobileV2/home?usersatoken";
    // JSON格式化对象
    private static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        // 启用JSON格式化输出
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
    }

    /**
     * 获取TOKEN接口 - 严格按照图片格式返回JSON
     */
    @Path("/getToken")
    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Produces(MediaType.APPLICATION_JSON)
    public String getToken(
            @FormParam("reqTime") String reqTime,
            @FormParam("serviceId") String serviceId,
            @FormParam("userNo") String userNo,
            @FormParam("hmac") String clientHmac) throws JsonProcessingException {

        // 按照图片要求创建有序Map，保证字段顺序：rbCode, code, rbMsg, saToken
        Map<String, Object> response = new LinkedHashMap<>();
        response.put("rbCode", "");
        response.put("code", 200);
        response.put("rbMsg", "");
        response.put("saToken", "");

        try {
            // 1. 参数校验 - 全部参数必须提供
            if (isEmpty(reqTime) || isEmpty(serviceId) || isEmpty(userNo) || isEmpty(clientHmac)) {
                response.put("code", 400); // HTTP 400 状态码
                response.put("rbCode", "J0000002"); // 用户名不可用
                response.put("rbMsg", "所有参数必须提供");
                return formatJsonResponse(response);
            }

            // 2. 验证服务ID
            if (!SERVICE_ID.equals(serviceId)) {
                response.put("code", 400); // HTTP 400 状态码
                response.put("rbCode", "J0000001"); // 业务返回码：服务ID不可用
                response.put("rbMsg", "无效的服务ID");
                return formatJsonResponse(response);
            }

            // 3. 验证签名
            String serverHmac = generateSignature(reqTime, serviceId, userNo, TRAD);
            if (!serverHmac.equals(clientHmac)) {
                response.put("code", 401); // HTTP 401 状态码
                response.put("rbCode", "J0000004"); // 业务返回码：签名验证不正确
                response.put("rbMsg", "签名验证失败");
                return formatJsonResponse(response);
            }

            // 4. 检查时间有效性（示例逻辑）
            if (isRequestTimeExpired(reqTime)) {
                response.put("code", 400); // HTTP 400 状态码
                response.put("rbCode", "J0000014"); // 业务返回码：请求时间已过期
                response.put("rbMsg", "请求时间已过期");
                return formatJsonResponse(response);
            }

            // 5. 构建外部请求URL
            String queryString = String.format("reqTime=%s&serviceId=%s&userNo=%s&hmac=%s",
                    URLEncoder.encode(reqTime, StandardCharsets.UTF_8),
                    URLEncoder.encode(serviceId, StandardCharsets.UTF_8),
                    URLEncoder.encode(userNo, StandardCharsets.UTF_8),
                    URLEncoder.encode(serverHmac, StandardCharsets.UTF_8));
            String fullUrl = TOKEN_URL + "&" + queryString;

            // 6. 发送外部请求
            URL url = new URL(fullUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Accept", "application/json");
            connection.setConnectTimeout(5000); // 5秒超时
            connection.setReadTimeout(10000); // 10秒超时

            // 7. 处理响应
            int httpCode = connection.getResponseCode();
            if (httpCode == HttpURLConnection.HTTP_OK) {
                String jsonResponse = readResponse(connection.getInputStream());
                Map<String, Object> tokenData = parseJsonResponse(jsonResponse);

                // 按图片要求设置响应
                response.put("rbCode", tokenData.getOrDefault("rbCode", ""));
                response.put("rbMsg", tokenData.getOrDefault("rbMsg", ""));
                response.put("saToken", tokenData.getOrDefault("saToken", ""));

                return formatJsonResponse(response);
            } else {
                // 外部服务错误
                response.put("code", 500); // HTTP 500 状态码
                response.put("rbMsg", "TOKEN服务请求失败: " + httpCode);
                return formatJsonResponse(response);
            }
        } catch (Exception e) {
            // 系统错误
            response.put("code", 500); // HTTP 500 状态码
            response.put("rbMsg", "系统错误: " + e.getMessage());
            return formatJsonResponse(response);
        }
    }

    /**
     * 检查参数是否为空
     */
    private boolean isEmpty(String value) {
        return value == null || value.trim().isEmpty();
    }

    /**
     * 检查请求时间是否过期（简化实现）
     */
    private boolean isRequestTimeExpired(String reqTime) {
        // 实际实现应包括时间解析和与当前时间比较的逻辑
        // 这里返回false仅用于演示
        return false;
    }

    /**
     * 生成MD5签名 - 严格按照图片顺序：reqTime + serviceId + userNo + trad
     */
    private String generateSignature(String reqTime, String serviceId, String userNo, String trad) {
        try {
            // 严格按照图片要求顺序拼接参数
            String data = reqTime + serviceId + userNo + trad;

            // 使用MD5算法生成签名
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hash = md.digest(data.getBytes(StandardCharsets.UTF_8));

            // 转换为小写十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            throw new RuntimeException("签名生成失败", e);
        }
    }

    /**
     * 读取HTTP响应内容
     */
    private String readResponse(InputStream inputStream) throws Exception {
        StringBuilder response = new StringBuilder();
        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }
        }
        return response.toString();
    }

    /**
     * 解析JSON响应
     */
    private Map<String, Object> parseJsonResponse(String json) {
        Map<String, Object> map = new LinkedHashMap<>();
        try {
            // 简化解析逻辑
            json = json.replace("{", "").replace("}", "").replace("\"", "");
            String[] pairs = json.split(",");

            for (String pair : pairs) {
                String[] parts = pair.split(":", 2);
                if (parts.length == 2) {
                    String key = parts[0].trim();
                    String value = parts[1].trim();
                    map.put(key, value);
                }
            }
        } catch (Exception e) {
            // 忽略解析错误，返回空map
        }
        return map;
    }

    /**
     * 格式化JSON响应 - 严格按照图片格式要求
     */
    private String formatJsonResponse(Map<String, Object> response) throws JsonProcessingException {
        // 严格按照图片要求的字段顺序：rbCode, code, rbMsg, saToken
        Map<String, Object> orderedResponse = new LinkedHashMap<>();
        orderedResponse.put("rbCode", response.get("rbCode"));
        orderedResponse.put("code", response.get("code"));
        orderedResponse.put("rbMsg", response.get("rbMsg"));
        orderedResponse.put("saToken", response.get("saToken"));

        return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(orderedResponse);
    }
}